//  Copyright (c) 2008  Yoong-ki Ahn & Youngjin Kim < mexif@googlegroups.com>
//  See the enclosed file COPYING for license information (MIT Licence).
//  If you did not receive this file,
//  see http://www.opensource.org/licenses/mit-license.php.

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS

#include "mexiflib.h"
#include "findfile.h"

void example_check_jpeg_has_exif( const wchar_t* filename );
void example_check_exif( const wchar_t* filename );
void example_dump_makernote( const wchar_t* filename );

struct content_t { unsigned char* p; size_t size; };
content_t load_file( const wchar_t* filename );
void scan_jpeg( content_t c );



int main( int argc, const char* argv[] )
{
	example_dump_makernote( L"..\\sample\\minolta\\*" );
	return 0;
}



content_t load_file( const wchar_t* filename )
{
	FILE* f = _wfopen( filename, L"rb" );
	content_t c;
	c.p = 0;
	c.size = 0;

	if ( f == 0 )
		return c;

	fseek( f, 0, SEEK_END );
	long end = ftell( f );
	fseek( f, 0, SEEK_SET );

	unsigned char* p = (unsigned char*) malloc( end );
	fread( p, 1, end, f );
	fclose( f );

	c.p = p;
	c.size = end;
	return c;
}

void scan_jpeg( content_t c )
{
}

void dump_tag( mexif_tag_t& tag, const wchar_t* indent )
{
	wchar_t		tag_name[64];
	wchar_t		value_type[128];
	memset( value_type, 0, sizeof(value_type) );

	{
		tag_name[0] = 0;
		mexif_pcstr t = mexif_tag_name( &tag );
		if ( t != 0 )
			wcscpy( tag_name, t );
		else
			wcscpy( tag_name, L"(null)" );

		size_t indent_len = 25 - wcslen(indent);
		size_t len = wcslen( tag_name );
		for ( ; len<indent_len; ++len )
			tag_name[len] = ' ';
		tag_name[indent_len] = 0;
	}

	switch( tag.value_type )
	{
	case MEXIF_VALUE_BYTE		: wcscpy( value_type, L"byte" );		break;
	case MEXIF_VALUE_ASCII		: wcscpy( value_type, L"ascii" );		break;
	case MEXIF_VALUE_UINT16		: wcscpy( value_type, L"uint16" );		break;
	case MEXIF_VALUE_UINT32		: wcscpy( value_type, L"uint32" );		break;
	case MEXIF_VALUE_RATIONAL	: wcscpy( value_type, L"rational" );	break;
	case MEXIF_VALUE_UNDEFINED	: wcscpy( value_type, L"undef" );		break;
	case MEXIF_VALUE_SINT8		: wcscpy( value_type, L"char" );		break;
	case MEXIF_VALUE_SINT16		: wcscpy( value_type, L"sint16" );		break;
	case MEXIF_VALUE_SINT32		: wcscpy( value_type, L"sint32" );		break;
	case MEXIF_VALUE_SRATIONAL	: wcscpy( value_type, L"srational" );	break;
	default :
		wcscpy( value_type, L"?" );
		MEXIF_ASSERT( 0 );
	}

	if ( tag.value_count > 1 )
	{
		size_t len = wcslen( value_type );
		swprintf( value_type + len, L"[%d] ", tag.value_count );
		len = wcslen( value_type );

		unsigned int max_char = 30;
		unsigned int n = 0;

		if ( tag.value_type == MEXIF_VALUE_ASCII )
		{
			n = max_char > tag.value_size ? tag.value_size : max_char;
			len = wcslen( value_type );
			value_type[len] = '"';

			for ( unsigned int i=0; i<n; ++i )
			{
				len = wcslen( value_type );
				value_type[len] = *(tag.value_pointer + i);
			}

			len = wcslen( value_type );
			value_type[len] = '"';
		}
		else if ( tag.value_type == MEXIF_VALUE_UNDEFINED || tag.value_type == MEXIF_VALUE_BYTE || tag.value_type == MEXIF_VALUE_SINT8 )
		{
			n = max_char >= tag.value_count*3 ? tag.value_count : max_char/3;
			len = wcslen( value_type );
			value_type[len] = '{';
			value_type[++len] = ' ';

			for ( unsigned int i=0; i<n; ++i )
			{
				len = wcslen( value_type );
				swprintf( value_type + len, L"%02x ", tag.value_pointer[i] );
			}

			len = wcslen( value_type );
			value_type[len] = '}';
		}
		else if ( tag.value_type == MEXIF_VALUE_UINT16 || tag.value_type == MEXIF_VALUE_SINT16 )
		{
			n = max_char >= tag.value_count*5 ? tag.value_count : max_char/5;
			len = wcslen( value_type );
			value_type[len] = '{';
			value_type[++len] = ' ';

			for ( unsigned int i=0; i<n; ++i )
			{
				len = wcslen( value_type );
				if ( tag.value_type == MEXIF_VALUE_UINT16 )
					swprintf( value_type + len, L"%04x ", mexif_tag_value_uint_index( &tag, i ) );
				else
					swprintf( value_type + len, L"%04x ", mexif_tag_value_int_index( &tag, i ) );
			}

			len = wcslen( value_type );
			value_type[len] = '}';
		}
		else if ( tag.value_type == MEXIF_VALUE_UINT32 || tag.value_type == MEXIF_VALUE_SINT32 )
		{
			n = max_char > tag.value_count*9 ? tag.value_count : max_char/9;
			len = wcslen( value_type );
			value_type[len] = '{';
			value_type[++len] = ' ';

			for ( unsigned int i=0; i<n; ++i )
			{
				len = wcslen( value_type );
				if ( tag.value_type == MEXIF_VALUE_UINT32 )
					swprintf( value_type + len, L"%08x ", mexif_tag_value_uint_index( &tag, i ) );
				else
					swprintf( value_type + len, L"%08x ", mexif_tag_value_int_index( &tag, i ) );
			}

			len = wcslen( value_type );
			value_type[len] = '}';
		}
	}
	else
	{
		size_t len = wcslen( value_type );
		if ( tag.value_type == MEXIF_VALUE_BYTE || tag.value_type == MEXIF_VALUE_UINT16 || tag.value_type == MEXIF_VALUE_UINT32 )
		{
			unsigned int ui = mexif_tag_value_uint( &tag );
			if ( ui < 0xffff )
				swprintf( value_type + len, L" %u", ui );
			else
				swprintf( value_type + len, L" 0x%x", ui );
		}
		else if ( tag.value_type == MEXIF_VALUE_SINT32 || tag.value_type == MEXIF_VALUE_SINT16 || tag.value_type == MEXIF_VALUE_SINT8 )
		{
			swprintf( value_type + len, L" %d", 
				mexif_tag_value_int( &tag )
				);
		}
		else if ( tag.value_type == MEXIF_VALUE_SRATIONAL || tag.value_type == MEXIF_VALUE_RATIONAL )
		{
			swprintf( value_type + len, L" %.3f", 
				mexif_tag_value_double( &tag )
				);
		}
	}

	wprintf( L"%s%3x %s %-10s\n", indent, tag.tag_id, tag_name, value_type );
}

void example_dump_makernote( const wchar_t* filename )
{
	wstring_list targets = LookupDirectory( filename );

	while( !targets.empty() )
	{
		std::wstring filename = targets.front();
		targets.pop_front();

		content_t c = load_file( filename.c_str() );

		mexif_jpeg_t h;

		if ( MEXIF_RET_OK != mexif_jpeg_init( &h, c.p, c.size ) )
			continue;

		for ( ; mexif_jpeg_isvalid( &h ); mexif_jpeg_next( &h ) )
		{
			int marker = mexif_jpeg_getmarker( &h );
			int len    = mexif_jpeg_getlength( &h );
			const unsigned char* chunk = (const unsigned char*) mexif_jpeg_getchunk( &h );

			if ( !mexif_jpeg_is_exif( &h ) )
				continue;

			wprintf( L"%-40s : ", filename.c_str()  );
			mexif_exif_t exif;
			mexif_exif_init( &exif, chunk+2, len-2  );

			if ( exif.core.makernote == 0 )
			{
				wprintf( L"\n" );
				continue;
			}

			mexif_rotate_t rot = mexif_get_rotation( &exif );
			wprintf( L"%s (rot:%d)\n", mexif_get_maker_str( exif.core.maker ), rot*90 );

 			mexif_section_t sec;
			mexif_section_select( &sec, &exif, MEXIF_SECTION_0 );
 			{
 				mexif_tag_t tag1, tag2;
				if ( mexif_select_tag( &sec, &tag1, MEXIF_TAGID_EXIF_ImageWidth ) &&
					 mexif_select_tag( &sec, &tag2, MEXIF_TAGID_EXIF_ImageHeight ) )
				{
 					wprintf( L"    %s=%d, %s=%d\n", 
 						mexif_tag_name( &tag1 ),
 						mexif_tag_value_uint( &tag1 ),
 						mexif_tag_name( &tag2 ),
 						mexif_tag_value_uint( &tag2 )
 						);
 				}
 			}
 			mexif_section_close( &sec ); 

 			mexif_section_select( &sec, &exif, MEXIF_SECTION_MAKERNOTE );

 			unsigned int count = mexif_count_tags( &sec );
 			for ( unsigned int i=0; i<count; ++i )
 			{
 				mexif_tag_t tag;
				if ( !mexif_select_tag( &sec, &tag, i ) )
				{
					wprintf( L"    %d th tag error.\n", i );
					continue;
				}
				dump_tag( tag, L"  " );

				if ( tag.value_format )
				{
					mexif_section_t subsec;
					mexif_subsection_load( &subsec, &tag );

					unsigned int count = mexif_count_tags( &subsec );
					for ( unsigned int j=0; j<count; ++j )
					{
						mexif_tag_t tag2;
						mexif_select_tag( &subsec, &tag2, j );
						dump_tag( tag2, L"    " );
					}

					mexif_section_close( &subsec );
				}
			}

			mexif_section_close( &sec );
			mexif_exif_close( &exif );

			//wprintf( L"  %x : %d\n", marker, len );
		}

		mexif_jpeg_close( &h );

		free( c.p );
	}
}

void example_check_exif( const wchar_t* filename )
{
	wstring_list targets = LookupDirectory( filename );

	while( !targets.empty() )
	{
		std::wstring filename = targets.front();
		targets.pop_front();

		content_t c = load_file( filename.c_str() );

		mexif_jpeg_t h;
		if ( MEXIF_RET_OK != mexif_jpeg_init( &h, c.p, c.size ) )
			continue;

		for ( ; mexif_jpeg_isvalid( &h ); mexif_jpeg_next( &h ) )
		{
			int marker = mexif_jpeg_getmarker( &h );
			int len    = mexif_jpeg_getlength( &h );
			const unsigned char* chunk = (const unsigned char*) mexif_jpeg_getchunk( &h );

			if ( mexif_jpeg_is_exif( &h ) )
			{
				//wprintf( L"%40s : %s\n", filename.c_str(), mexif_maker_str[exif.maker] );
			}

			//wprintf( L"  %x : %d\n", marker, len );
		}

		mexif_jpeg_close( &h );

		free( c.p );
	}

}

void example_check_jpeg_has_exif( const wchar_t* filename )
{
	wstring_list targets = LookupDirectory( filename );

	while( !targets.empty() )
	{
		std::wstring filename = targets.front();
		targets.pop_front();

		content_t c = load_file( filename.c_str() );

		mexif_jpeg_t h;
		if ( MEXIF_RET_OK != mexif_jpeg_init( &h, c.p, c.size ) )
			continue;

		for ( ; mexif_jpeg_isvalid( &h ); mexif_jpeg_next( &h ) )
		{
			int marker = mexif_jpeg_getmarker( &h );
			int len    = mexif_jpeg_getlength( &h );

			if ( mexif_jpeg_is_exif( &h ) )
			{
				wprintf( L"%s  has exif %d bytes\n", filename.c_str(), len );
			}

			//wprintf( L"  %x : %d\n", marker, len );
		}

		mexif_jpeg_close( &h );

		free( c.p );
	}

}
